<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>js面试题</title>
    <link rel="stylesheet" href="../1style/index.css"/>
    <script src="../1style/jquery.js"></script>
</head>
<body>

<h3>var语句多次声明一个变量,会不会报错</h3>
<div>
    <pre>
    1.使用var语句多次声明一个变量不仅是合法的,而且也不会造成任何错误.
    2.如果重复使用的一个声明有一个初始值,那么它担当的不过是一个赋值语句的角色.
    3.如果重复使用的一个声明没有一个初始值,那么它不会对原来存在的变量有任何的影响.
    </pre>
</div>

<h3>call 和 apply 和 bind 的区别</h3>
<div>
    <pre>
    1.都是fn原型上的方法 Function.prototype.myCall = function (context, ...args)
    2.fn.call(F1,a1,a2) 这个用的比较多一点,因为更像方法的调用
    3.fn.apply(F1,[a1,a2]) 参数写在一个数组中
    4.newFn = fn.bind(F1,a1,a2) 返回是一个新的函数,调用newFn()后才会执行
    https://www.bilibili.com/video/BV1m54y1q7hc
    https://www.bilibili.com/video/BV1wK4y1Y7kP
    </pre>
</div>

<h3>null和undefined的区别</h3>
<div>
    <pre>
        相同点: if判断 都是false
        不同点: null表示一个值被定义了，但是这个值是空值&&&&变量被声明了还没有赋值，就为undefined
        undefined和数值+-*/是NAN
        null和数值+-*/ null变成0
        https://www.bilibili.com/video/BV1N54y1i7UL 厕所卷纸形象描述
    </pre>
</div>

<h3>P.x和P['x']的区别</h3>
<div>
    <pre>
        P.x访问时，只能固定访问属性名为x的属性；
        而P['x']比较灵活，可以动态的修改[ ]内字符串的值，来访问不同的属性，如P['x'+i]
    </pre>
</div>

<h3><span>命中</span>for in和for of的区别</h3>
<div>
    <pre>
        for in 遍历 数组 或者 对象的属性。
        for in得到对对象的key或数组,字符串的下标,对象原型链上的属性方法一块遍历
        for of和forEach一样,是直接得到值
        for of不能对象用,可以用于api await等待调用
    </pre>
</div>

<h3>Object.create()和new object()和{}的区别</h3>
<div>
    <pre>
        //{}:字面量创建对象和new Object()并无区别，默认都是继承了Object对象上的prototype
        1.o=Object.create(a,b) 0.__proto__ === a; 对象o的值是b
        2.new object() 创建过程 也是new的过程 就是 构造函数实例化对象 所以速度比{}慢一点
        2.new object() 可以传参 new object(null) String Number
        https://www.cnblogs.com/leijee/p/7490822.html
        https://www.bilibili.com/video/BV1Xk4y1172Y
    </pre>
</div>

<h3>new操作符具体干了什么呢</h3>
<div>
    <pre>
    对应伪代码：
    对于const a = new Foo();  new干了以下事情 4个步骤
    const o = new Object();//创建了一个新的空对象o
    o.__proto__ = Foo.prototype;//让这个o对象的` __proto__`指向函数的原型`prototype`
    Foo.call(o); // this指向o对象
    a = o; // 将o对象赋给a对象
    </pre>
</div>

<h3><span>命中</span>比如a = [1,2,3,4,5]，怎么把a转为对象</h3>
<div>
    <pre>
        Object.assign({},[1,2,3,4,5]) 可以实现互转
    </pre>
</div>

<h3>Cookie、session和localStorage、以及sessionStorage之间的区别</h3>
<div>
    <pre>
    cookie的内容主要包括：名字、值、过期时间、路径和域,不设置时间关闭浏览器窗口，cookie就会消失,
    cookie设置时间保存在硬盘上,不设置时间,保存在内存中,Cookies跨域也存在问题
    session数据放在服务器上,session中保存的是对象，cookie中保存的是字符串
    Storage大小5M,localStorage本地永久存储
    sessionStorage当前会话有效,刷新页面数据依旧存在。但是关闭后消失
    https://www.bilibili.com/video/BV1ut411j7R7
    </pre>
</div>

<h3>Cookie、session token 区别</h3>
<div>
    <pre>
    token 密钥掌握在服务器端口, 前端可以任意传输 无所谓
    多域名传递登录信息
    https://www.bilibili.com/video/av55464913/?p=10
    </pre>
</div>

<h3>JSON 的了解？</h3>
<div>
    <pre>
    1、json有两种格式就是对象和数组，它是javascript的一个子集
    2、对象在js中表示就是用{}包裹起来的，里面就是键值对。调用的时候就直接key就可以调用它的值
    3、数组就是用[]包裹起来，取值的时候是通过它的索引值
    4、常用的json就是将json转换成字符串用JSON.stringify，会忽略undefined，function，Symbol，
       不能正确处理 NaN，Infinity，循环引用。不认识的转为null
       非数组对象的属性不能保证以特定的顺序出现在序列化后的字符串中。
       转换对象值如果有 toJSON() 函数，该函数返回什么值，序列化结果就是什么值，并且忽略其他属性的值。
    5、字符串转换成对象JSON.parse，目的就是替换掉麻烦的xml
    </pre>
</div>

<h3>如何判断当前脚本运行在浏览器还是node环境中</h3>
<div>
    <pre>
    typeof window === 'undefined'
    通过判断Global对象是否为window，如果不为window就不是浏览器
    </pre>
</div>

<h3>window对象，是JS的最顶层对象，其他的 BOM 对象都是 window 对象的属性</h3>
<div>
    <pre>
        location 对象，浏览器当前URL信息；  navigator 对象，浏览器本身信息；
        screen 对象，客户端屏幕信息；  history 对象，浏览器访问历史信息；
    </pre>
</div>

<h3>Promise构造函数是同步还是异步执行，then呢</h3>
<div>
    <pre>
    Promise 构造函数是同步执行的，promise.then 中的函数是异步执行的。
    </pre>
</div>

<h3>事件循环机制 Event Loop</h3>
<div>
    <pre>
        new Promise() 是同步执行  then 才是异步
        先微任务后宏任务 then属于微任务
        https://www.cnblogs.com/cangqinglang/p/8967268.html
    </pre>
</div>

<h3>Promise有几个状态</h3>
<div>
    <pre>
    Promise有三种状态：pending(进行中)、resolved(成功)、rejected(失败)
    promise 状态一旦改变则不能再变。
    </pre>
</div>

<h3>Promise的原理async+await的原理</h3>
<div>
    <pre>
        https://www.bilibili.com/video/BV12t4y1e7Uh
    </pre>
</div>

<h3>Promise和setTimeout执行先后的区别</h3>
<div>
    <pre>
        promise比setTimeout先执行的
    </pre>
</div>

<h3>常用的设计模式</h3>
<div>
    <pre>

    </pre>
</div>

<h3>箭头函数与普通函数有什么区别?</h3>
<div>
    <pre>
        1.没有原型链(没有constructor属性)所以不能实例化
        2.没有this. 3.没有ang
    </pre>
</div>

<h3><span>命中</span>es6类class和继承的实现原理</h3>
<div>
    <pre>
        https://blog.csdn.net/qq_34149805/article/details/86105123
    </pre>
</div>

<h3>class继承?</h3>
<div>
    <pre>
        1.constructor new的时候自动调用, 继承的时候一定要 super()一下
        2.有简写方法,class Person{ name=23;}和class Person{this.name=23;}是一样的
    </pre>
</div>

<h3>JavaScript如何实现继承？</h3>
<div>
    <pre>
        1222222222222222222
    </pre>
</div>

<h3>ES5/ES6 的继承除了写法以外还有什么区别？</h3>
<div>
    <pre>
    1222222222222222222
    </pre>
</div>

<h3>关于js中function和class的内在关系及区别的理解</h3>
<div>
    <pre>
    1.class的2种声明 class Rectangle{} || let Rectangle = class {}
    2.class要先声明在使用,fn不会
    3.通过super关键字，调用父类的constructor方法。
    4、static和prototype method的封装 当static或prototype method被调用的时候，如果没有对this赋值，
    　 那么this将是undefined状态。这和是否采用static模式无关，因为class类体中的代码已经默认执行static模式。
    https://www.cnblogs.com/dunaiyang/p/9330003.html
    https://www.bilibili.com/video/BV1w7411d7rC?p=10 // es6的class有哪些特性
    </pre>
</div>

<h3>介绍下浏览器跨域,怎么去解决跨域问题,Ajax发生跨域要设置什么（前端）,csrf跨域攻击的安全性问题怎么防范</h3>
<div>
    <pre>
    同源策略即：同一协议，同一域名，同一端口号。当其中一个不满足时，我们的请求即会发生跨域问题。
    JSONP核心就是:我们要用过利用img、script，link标签的src或href属性（到底使用那个标签无所谓）来实现,只能发送get请求。因为script只能发送get请求
    CSRF攻击的全称是跨站请求伪造（ cross site request forgery) , 验证码 ref来源地址
    </pre>
</div>

<h3><span>命中</span>跨域,跨域解决的办法</h3>
<div>
    <pre>
        浏览器的同源策略限制,就是跨域了,无法请求,无法接触非同源网页的 DOM,无法读取非同源网页的 Cookie、LocalStorage
        解决:代理,JSONP script、img这样的获取资源的标签是没有跨域限制的，利用这一点，我们可以这样干 JSONP只能发GET请求
        iframe+form 解决post请求
        CORS 后台设置header
        代理转发
        window.postMessage()
        document.domain 2个页面都要设置 因为要把端口忽略为null
        https://segmentfault.com/a/1190000015597029
        https://www.bilibili.com/video/av55464913/?p=11
    </pre>
</div>

<h3>如果解决ajax无法后退的问题？</h3>
<div>
    <pre>
        History对象
            window.history.back()	//浏览器点击后退
            window.history.forward()//浏览器点击前进
            window.history.go(number)      // 进入某个历史
        HTML5为history对象添加了两个新方法，
        history.pushState(data, title [,url])
        history.replaceState(data, title [,url])，
    </pre>
</div>

<h3>websocket和ajax轮询</h3>
<div>
    <pre>
    websocket 只需要链接一次
    ajax轮询的原理非常简单, 让浏览器每隔几秒发送一次请求,可以提现HTTP协议的另外一个特点,被动性(只能在这等, 谁请求服务器,才能给谁).
    同时,http的每一次请求与响应结束后, 服务器将客户端信息全部丢弃, 下次请求,必须携带身份信息(cookie),无状态性;
    </pre>
</div>

<h3>介绍一下闭包和闭包常用场景？为什么会出现闭包这种东西？解决了什么问题？</h3>
<div>
    <pre>
    闭包是指:: 有权访问另一个函数作用域中的变量的函数
    受JavaScript链式作用域结构的影响，父级变量中无法访问到子级的变量值，为了解决这个问题，才使用闭包这个概念
    闭包的缺点就是常驻内存，会增大内存使用量，使用不当很容易造成内存泄露
    </pre>
</div>

<h3>介绍一下你所了解的作用域链，作用域链的尽头是什么？为什么？</h3>
<div>
    <pre>
    作用域的特点就是，先在自己的变量范围中查找，如果找不到，就会沿着作用域往上找。
    https://www.jianshu.com/p/2c3c8890dff0
    </pre>
</div>

<h3>javascript的内存回收机制？</h3>
<div>
    <pre>
    内存的生命周期:
        内存分配：当我们申明变量、函数、对象的时候，系统会自动为他们分配内存
        内存使用：即读写内存，也就是使用变量、函数等
        内存回收：使用完毕，由垃圾回收机制自动回收不再使用的内存
    2. 标记清除————
    2. 引用计数————
    </pre>
</div>

<h3>some、every、find、filter、map、forEach有什么区别</h3>
<div>
    <pre>
    map():返回一个新的Array，每个元素为调用func的结果
    filter():返回一个符合func条件的元素数组
    some():  返回一个boolean，判断是否有元素是否符合func条件
    every(): 返回一个boolean，判断每个元素是否符合func条件
    forEach():没有返回值，只是针对每个元素调用func
    </pre>
</div>

<h3>介绍下 Set、Map、WeakSet 和 WeakMap 的区别</h3>
<div>
    <pre>
        https://www.bilibili.com/video/BV1w7411d7rC?p=8
        Set 类似于数组，成员唯一， [Value, value]的形式储存
        Set集合转数组 Array.from(new Set(array))||[...new Set(array)]
    </pre>
</div>

<h3>['1', '2', '3'].map(parseInt) what & why ?</h3>
<div>
    <pre>
        https://www.bilibili.com/video/BV1w7411d7rC?p=6&spm_id_from=pageDriver
        返回[1,NAN,NAN]
    </pre>
</div>

<h3>什么是防抖和节流？有什么区别？如何实现</h3>
<div>
    <pre>
    https://v.youku.com/v_show/id_XNDE3MzM5MTQ5Ng==.html
    防抖:return 一个函数, 用setTimeout(鼠标滚动事件) input 输入 窗口变化 终止删除前一个
    节流:固定时间内只能执行一次
    </pre>
</div>

<h3>详解JS函数柯里化/反柯里化</h3>
<div>
    <pre>
    fn(1,2,3) = 6; 变参数变少就是 柯里化  fn(1)(2)(3),其实也就是一个毕包
    </pre>
</div>

<h3><span>命中</span>数组的去重</h3>
<div>
    <pre>
        1.es6的 set new Set([1,1,1,3,4,4,4,2])
        2.遍历函数去重
        2.转为对象 对象的key只有一个
    </pre>
</div>

<h3>冒泡排序,二分算法(快速排序)什么是纯函数</h3>
<div>
    <pre>
    1.纯函数: 相同的输入,会得到相同的结果
    2.冒泡排序: 就是两两比较 https://www.bilibili.com/video/BV1bG4y1E7oX
    3.二分查找法: 就是取一个标杆,左右分散 https://www.bilibili.com/video/BV1bG4y1E7oX
    </pre>
</div>

<h3>关于事件冒泡、事件捕获、事件委托</h3>
<div>
    <pre>
    事件委托: 是一种技术,利用事件冒泡的特性,解决子节点事件绑定。
    事件冒泡: 当前触发的事件目标一级一级往上传递，依次触发，直到document为止。
    事件捕获: 会从document开始触发，一级一级往下传递，依次触发，直到真正事件目标为止。
    </pre>
</div>

<h3>如何阻止DOM的冒泡事件,和默认事件</h3>
<div>
    <pre>
    event.stopPropagation(); // 阻止冒泡
    event.preventDefault();  // 阻止冒泡和默认事件
    return false；:他会同事阻止事件冒泡也会阻止默认事件
    </pre>
</div>

<h3>event.stopPropagation()与event.preventDefault()</h3>
<div>
    <pre>
    stopPropagation:这是阻止事件的冒泡方法，不让事件向documen上层蔓延，但是默认事件任然会执行，当你调用这个方法的时候，如果点击一个连接，这个连接仍然会被打开。
    preventDefault:这是阻止默认事件的方法，调用此方法是，连接不会被打开，但是会发生冒泡，冒泡会传递到上一层的父元素，此方法可以控制一些按钮在点击时只触发时间而不会引起表单的提交。
    return false；:他会同事阻止事件冒泡也会阻止默认事件
    </pre>
</div>

<h3>数组的扁平化,求数组的最大值</h3>
<div>
    <pre>
        数组扁平化: 将多维数组变为一维数组
        1.toString 后再split(,)  2.flat方法(ES10) 3.深度递归
        求数组的最大值 Math.max.apply(null,[12,333]) || Math.max(...[1,23,4,44])
    </pre>
</div>

<h3>深拷贝和浅拷贝</h3>
<div>
    <pre>
        浅拷贝:2个数组的合并 就是浅拷贝  Array.from() Object.assign({},c)
        浅拷贝: JSON  但会忽略undefined、任意的函数、symbol 值
    </pre>
</div>

<h3>import和require的区别</h3>
<div>
    <pre>
    require  CommonJS/AMD      运行时加载
    import   ESMAScript6+      编译时加载
    •require是赋值过程，其实require的结果就是对象、数字、字符串、函数等，再把require的结果赋值给某个变量
    •import是解构过程，但是目前所有的引擎都还没有实现import，也仅仅是将ES6转码为ES5再执行，import语法会被转码为require
    </pre>
</div>

<h3>变量函数提升与执行上下文</h3>
<div>
    <pre>
    变量提升: 代码预解析时，在作用域顶部定义 (无 var 没有变量提升,如何避免变量提升：使用 let 和 const 关键字)
    </pre>
</div>

<h3>函数中的变量提升</h3>
<div>
    <pre> //尚硅谷经典前端面试题精讲第一季(web前端大咖总结) https://www.bilibili.com/video/BV1nb411P7tQ?p=1
    var num1= 55
    var num2= 66
    function f1(num, num1){
        num=100;
        num1=100;
        num2=100; // 变量提升了
        console.log(num) // 100
        console.log(num1)// 100
        console.log(num2)// 100
    }
    f1(num1, num2)
    console.log(num1) // 55
    console.log(num2) // 100
    console.log(num)  // 报错
    </pre>
</div>

<h3>所以为什么 JS 的 typeof 不需要括号 （如何判断数据类型）</h3>
<div>
    <pre>
    JS 中的判断基本数据类型的四个方法: typeof, instanceof, constructor, prototype
    实际上 typeof 并不是一个函数，也不是一个语句，而是一个一元运算符（就像 ++, –, !）
    instanceof 不是函数，是一个双目运算符如 +, -
    </pre>
</div>

<h3>typeof的优缺点</h3>
<div>
    <pre>
    基本类型：undefined,number,string,boolean,object,function 都是小写
    引用类型：Object、Array、Date、Function、Error、RegExp、Math、Number、Global。
    typeof:（可以对基本类型做出准确的判断，但对于引用类型，用它就有点力不从心了）
    a instanceof b （a是否是b的实例）返回值为 true，false
    let num = 1; num instanceof Number //结果是false 就是缺点
    num.__proto__ === Number.prototype // true
    </pre>
</div>

<h3>严格模式有什么好处</h3>
<div>
    <pre>
　　- 消除Javascript语法的一些不合理、不严谨之处，减少一些怪异行为; - 消除代码运行的一些不安全之处，保证代码运行的安全；
　　- 提高编译器效率，增加运行速度； - 为未来新版本的Javascript做好铺垫

    "use strict" 开启严格模式 必须是脚本开始第一行，否则无效
    严格模式下, delete运算符后跟随非法标识符(即delete 不存在的标识符)，会抛出语法错误； 非严格模式下，会静默失败并返回false
    严格模式中，对象直接量中定义同名属性会抛出语法错误； 非严格模式不会报错
    严格模式中，函数形参存在同名的，抛出错误； 非严格模式不会
    严格模式不允许八进制整数直接量
    严格模式中，arguments对象是传入函数内实参列表的静态副本；非严格模式下，arguments对象里的元素和对应的实参是指向同一个值的引用
    严格模式中 eval和arguments当做关键字，它们不能被赋值和用作变量声明
    严格模式会限制对调用栈的检测能力，访问arguments.callee.caller会抛出异常
    严格模式 变量必须先声明，直接给变量赋值，不会隐式创建全局变量，不能用with,
    严格模式中 call apply传入null undefined保持原样不被转换为window
    </pre>
</div>

<h3>取数组的最大值（ES5、ES6）</h3>
<div>
    <pre>
    Math.max.apply(null, [14, 3, 77, 30]);  // ES5 的写法
    Math.max(...[14, 3, 77, 30]);           // ES6 的写法
    [14,3,77,30].reduce((accumulator, currentValue)=>{
        return accumulator = accumulator > currentValue ? accumulator : currentValue
    });
    </pre>
</div>

<h3>结构赋值-内部是怎么实现的</h3>
<div>
    <pre>
        对象的解构赋值的内部机制，是先找到同名属性，然后再赋给对应的变量。真正被赋值的是后者，而不是前者
        let { foo: baz } = { foo: 'aaa', bar: 'bbb' }; // {foo: foo } = {foo} 同名而已
        baz // "aaa"
        foo // error: foo is not defined
    </pre>
</div>

<h3> ... 扩展运算符||rest运算符</h3>
<div>
    <pre>
        console.log(...[1,2,3,4],[..."String"]);//1 2 3 4  // 打散数组 和字符串
        [...arr1, ...arr2, ...arr3] // 数组合并
        console.log([...document.querySelectorAll('div')]); // 将伪数组(nodeList对象)转化为数组

            rest 运算符简介 - 剩余运算符（the rest operator）
            var array = [1,2,3,4,5,6];  var [a,b,...c] = array;
            console.log(a,b); //1 , 2
            console.log(c);   //[3, 4, 5, 6]
    </pre>
</div>

</body>
</html>

<script>
    $(function () {
        $("h3").click(function () {
            $(this).next().toggle();
        });
    })
</script>

